package com.calvin.android.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class HTTPUtils {
	

	public static void ajax(String url, String type, boolean isMutilpart, Map<String, String> header, Map<String, List<Object>> data, OnHTTPListener listener) {
		if (url != null) {
			try {
				URL url2 = new URL(url);
				String boundary = String.format("----CalvinFormBoundary%s", new Date().getTime());
				HttpURLConnection conn = (HttpURLConnection) url2.openConnection();
				conn.setRequestMethod(type == null ? "GET" : type);
				conn.setReadTimeout(10000);
				conn.setUseCaches(true);
				conn.setDoInput(listener != null);
				if (header != null) {
					for (Entry<String, String> entry : header.entrySet()) {
						conn.setRequestProperty(entry.getKey(), entry.getValue());
					}
				}
				if (isMutilpart) {
					conn.setRequestProperty("Content-Type", String.format("multipart/form-data; boundary=%s", boundary));
				}
				conn.setDoOutput(conn.getRequestMethod().equals("POST") && data != null);
				conn.connect();
				if (conn.getDoOutput()) {
					OutputStream outputStream = conn.getOutputStream();
					if (isMutilpart) {
						boundary = String.format("--%s", boundary);
						for (Entry<String, List<Object>> entry : data.entrySet()) {
							for (Object object : entry.getValue()) {
								outputStream.write(String.format("%s\r\nContent-Disposition: form-data; name=\"%s\"", boundary, entry.getKey()).getBytes());
								if (object instanceof File) {
									File file = (File) object;
									outputStream.write(String.format("; filename=\"%s\"\r\nContent-Type: text/plain\r\n\r\n", file.getName()).getBytes());
									FileInputStream fileInputStream = new FileInputStream(file);
									writeToStream(fileInputStream, outputStream);
									fileInputStream.close();
									outputStream.write("\r\n".getBytes());
								} else {
									outputStream.write(String.format("\r\n\r\n%s\r\n", entry.getValue()).getBytes());
								}
							}
						}
						outputStream.write(String.format("%s--\r\n", boundary).getBytes());
					} else {
						StringBuilder builder = new StringBuilder();
						for (Entry<String, List<Object>> entry : data.entrySet()) {
							for (Object object : entry.getValue()) {
								builder.append(String.format("%s%s=%s", builder.length() == 0 ? "" : "&", entry.getKey(), object));
							}
						}
						outputStream.write(builder.toString().getBytes());
					}
					outputStream.close();
				}
				if (listener != null) {
					InputStream inputStream = conn.getInputStream();
					listener.onHandler(conn.getResponseCode(), conn.getHeaderFields(), inputStream);
					inputStream.close();
				}
				conn.disconnect();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static void get(String url, Map<String, String> header, OnHTTPListener listener) {
		ajax(url, "GET", false, header, null, listener);
	}

	public static void get(String url, OnHTTPListener listener, String... argv) {
		if (argv.length >= 0 && argv.length % 2 == 0) {
			Map<String, String> header = new HashMap<String, String>();
			for (int i = 0; i < argv.length / 2; i++) {
				header.put(argv[i * 2], argv[i * 2 + 1]);
			}
			ajax(url, "GET", false, header, null, listener);
		}
	}

	public static byte[] get(String url, String... argv) {
		final ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
		get(url, new OnHTTPListener() {
			public void onHandler(int code, Map<String, List<String>> header, InputStream inputStream) {
				if (code == 200) {
					writeToStream(inputStream, arrayOutputStream);
				}
			}
		}, argv);
		byte[] buffer = arrayOutputStream.toByteArray();
		try {
			arrayOutputStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return buffer;
	}

	public static void post(String url, Map<String, String> header, Map<String, List<Object>> data, OnHTTPListener listener) {
		ajax(url, "POST", false, header, data, listener);
	}

	public static void post(String url, Map<String, List<Object>> data, OnHTTPListener listener) {
		ajax(url, "POST", false, null, data, listener);
	}

	public static void postMutilpart(String url, Map<String, String> header, Map<String, List<Object>> data, OnHTTPListener listener) {
		ajax(url, "POST", true, header, data, listener);
	}

	public static void postMutilpart(String url, Map<String, List<Object>> data, OnHTTPListener listener) {
		ajax(url, "POST", true, null, data, listener);
	}

	public static byte[] readyByteArray(InputStream inputStream) {
		if (inputStream != null) {

			byte[] buffer = new byte[1024];
			int len = 0;
			try {
				ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
				while ((len = inputStream.read(buffer)) > 0) {
					byteArrayOutputStream.write(buffer, 0, len);
				}
				buffer = byteArrayOutputStream.toByteArray();
				byteArrayOutputStream.close();
				return buffer;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	public static String readyString(InputStream inputStream) {
		byte[] buffer = readyByteArray(inputStream);
		return buffer != null ? new String(buffer) : "";
	}

	public static boolean writeToStream(InputStream inputStream, OutputStream outputStream) {
		if (inputStream != null && outputStream != null) {
			byte[] buffer = new byte[1024];
			int len = 0;
			try {
				while ((len = inputStream.read(buffer)) > 0) {
					outputStream.write(buffer, 0, len);
				}
				return true;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

}
